/*
 * Copyright (c) Jack魏 2023 - 2024, All Rights Reserved.
 */

package cn.jackwei.yiyi.service.sys;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.jackwei.yiyi.exception.BusinessException;
import cn.jackwei.yiyi.mapper.SysLoginMapper;
import cn.jackwei.yiyi.mapper.SysUserMapper;
import cn.jackwei.yiyi.pojo.bean.SysLogin;
import cn.jackwei.yiyi.pojo.bean.SysUser;
import cn.jackwei.yiyi.pojo.constant.CommonConsts;
import cn.jackwei.yiyi.pojo.query.SysUserQuery;
import cn.jackwei.yiyi.pojo.vo.SysUserForgetVO;
import cn.jackwei.yiyi.pojo.vo.SysUserLoginVO;
import cn.jackwei.yiyi.pojo.vo.SysUserUpdateVO;
import cn.jackwei.yiyi.pojo.vo.SysUserVO;
import cn.jackwei.yiyi.util.MyCacheUtil;
import cn.jackwei.yiyi.util.Result;
import cn.jackwei.yiyi.util.SecurityUtil;
import cn.jackwei.yiyi.util.WebUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Objects;

/**
 * 系统用户服务类
 *
 * @author Jack魏
 * @since 2023/11/11
 */
@Slf4j
@Service
public class SysUserService extends ServiceImpl<SysUserMapper, SysUser> {
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysLoginMapper sysLoginMapper;

    /**
     * 注册用户
     *
     * @param vo 用户信息
     * @return 注册用户是否成功
     */
    public Integer register(SysUserVO vo) throws BusinessException {
        final String code = MyCacheUtil.get(vo.getCaptchaKey());
        if (!vo.getCaptcha().equals(code)) {
            throw new BusinessException("验证码错误！");
        }
        // 密码加密
        vo.setPassword(SecurityUtil.getBCryptPassword(vo.getPassword()));
        return saveUser(vo);
    }

    /**
     * 保存用户，默认插入id
     *
     * @param vo 用户信息
     * @return 是否成功
     */
    private Integer saveUser(SysUserVO vo) {
        // 如果已经有用户名存用在，注册就失败
        SysUser user = sysUserMapper.selectByAccount(vo.getAccount());
        if (user != null) {
            return 0;
        }
        // 拷贝对象
        user = new SysUser();
        BeanUtil.copyProperties(vo, user);
        // 雪花id
        user.setId(IdUtil.getSnowflakeNextId());
        return sysUserMapper.insert(user);
    }

    /**
     * 根据登录名，获取用户信息
     *
     * @param account 登录名
     * @return 用户信息
     */
    public SysUser getByAccount(String account) {
        return sysUserMapper.selectByAccount(account);
    }

    /**
     * 根据用户id获取用户数据
     *
     * @param userId 用户id
     * @return 用户信息
     */
    public SysUser getById(Serializable userId) {
        return sysUserMapper.selectById(userId);
    }

    /**
     * 登录
     *
     * @param request 请求信息
     * @param vo      登录信息
     * @return 登录用户信息
     */
    public Result<SysUser> login(HttpServletRequest request, SysUserLoginVO vo) {
        final String code = MyCacheUtil.get(vo.getCaptchaKey());
        if (!vo.getCaptcha().equals(code)) {
            return Result.fail("验证码错误！");
        }
        final SysUser user = getByAccount(vo.getAccount());
        if (user == null || !SecurityUtil.checkBCryptPassword(vo.getPassword(), user.getPassword())) {
            return Result.fail("账号密码错误！");
        }
        if (!Objects.equals(user.getStatus(), CommonConsts.NORMAL)) {
            return Result.fail("账号已被禁用！");
        }
        // 会话登录
        StpUtil.login(user.getId());
        // 在登录时缓存 user 对象
        StpUtil.getSession().set(user.getId().toString(), user);
        // 处理用户登陆
        doUserLogin(request, user);
        return Result.success(user);
    }

    /**
     * 用户登陆表操作
     *
     * @param request 请求
     * @param user    用户信息
     */
    private void doUserLogin(HttpServletRequest request, SysUser user) {
        // 不管有没有都需要插入
        SysLogin sysLogin = new SysLogin();
        sysLogin.setUserId(user.getId());
        sysLogin.setIp(WebUtil.getIpAddress(request));
        sysLogin.setStatus(1);
        sysLogin.setIpCity(WebUtil.getCityInfo(sysLogin.getIp()));
        sysLogin.setToken(StpUtil.getTokenValue());
        sysLogin.setExpireTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 30, ChronoUnit.DAYS));
        final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
        // 获取客户端操作系统
        String os = userAgent.getOs().getName();
        // 获取客户端浏览器
        String browser = userAgent.getBrowser().getName();
        sysLogin.setOs(os);
        sysLogin.setBrowser(browser);
        sysLoginMapper.insert(sysLogin);
    }

    /**
     * 忘记密码
     *
     * @param vo 更改信息
     * @return 是否修改成功
     */
    public Result<String> forget(SysUserForgetVO vo) {
        final String code = MyCacheUtil.get(vo.getCaptchaKey());
        if (!vo.getCaptcha().equals(code)) {
            return Result.fail("验证码错误！");
        }
        final SysUser user = getByAccount(vo.getAccount());
        if (user == null || !user.getPhone().equals(vo.getPhone())) {
            return Result.fail("账号信息不匹配！");
        }
        SysUser update = new SysUser();
        update.setId(user.getId());
        update.setPassword(SecurityUtil.getBCryptPassword(vo.getPassword()));
        updateById(update);
        StpUtil.logout();
        return Result.successMsg("修改成功，请重新登录~");
    }

    /**
     * 更新用户信息
     *
     * @param vo 用户信息
     * @return 用户信息
     */
    public Result<Object> updateUser(SysUserUpdateVO vo) {
        SysUser update = new SysUser();
        BeanUtil.copyProperties(vo, update);
        // 新增用户
        if (vo.getId() == null) {
            SysUserVO newUser = new SysUserVO();
            BeanUtil.copyProperties(vo, newUser);
            // 密码加密
            newUser.setPassword(SecurityUtil.getBCryptPassword(SecurityUtil.DEFAULT_PASSWORD));
            Integer result = saveUser(newUser);
            if (result > 0) {
                return Result.success(newUser);
            } else {
                return Result.fail("账号已存在！");
            }
            // 修改用户
        } else {
            update.setId(vo.getId());
            updateById(update);
            // 获取新用户
            final SysUser newUser = getById(vo.getId());
            // 更新登录时缓存 user 对象
            StpUtil.getSession().set(newUser.getId().toString(), newUser);
            return Result.success(newUser);
        }
    }

    /**
     * 根据条件查询用户信息
     *
     * @param query 条件
     * @return 用户信息
     */
    public Page<SysUser> pageUser(SysUserQuery query) {
        return baseMapper.pageUser(query);
    }
}
